package ucla.axelia.controlador.servicios;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;

import ucla.axelia.controlador.interfaces.IServicioAdministracionPostularVoluntarios;
import ucla.axelia.modelo.beans.EstadoVoluntario;
import ucla.axelia.modelo.beans.RespuestaCerrada;
import ucla.axelia.modelo.dao.ServicioPostuladoTemporalDAO;
import ucla.axelia.modelo.dao.ServicioReconocimientoDAO;
import ucla.axelia.modelo.dao.ServicioReconocimientoVoluntarioDAO;
import ucla.axelia.modelo.dao.ServicioVoluntarioDAO;
import ucla.axelia.modelo.data.ActividadPlanificada;
import ucla.axelia.modelo.data.AsistenciaVoluntario;
import ucla.axelia.modelo.data.DataGenerica;
import ucla.axelia.modelo.data.PostuladosTemporal;
import ucla.axelia.modelo.data.Reconocimiento;
import ucla.axelia.modelo.data.ReconocimientoRequerido;
import ucla.axelia.modelo.data.ReconocimientoVoluntario;
import ucla.axelia.modelo.data.TipoActividadRequerida;
import ucla.axelia.modelo.data.Voluntario;
import ucla.axelia.modelo.pk.PostuladosTemporalId;

public class ServicioAdministracionPostularVoluntarios implements IServicioAdministracionPostularVoluntarios {

	ServicioReconocimientoDAO servicioReconocimientoDAO;
	ServicioVoluntarioDAO servicioVoluntarioDAO;
	ServicioPostuladoTemporalDAO servicioPostuladoTemporalDAO;
	ServicioReconocimientoVoluntarioDAO servicioReconocimientoVoluntarioDAO;
	
	public List<PostuladosTemporal> postularParaTodos() {
		List<PostuladosTemporal> postulados = new ArrayList<PostuladosTemporal>();
		List<Reconocimiento> reconocimientos = servicioReconocimientoDAO.buscarTodos(DataGenerica.DATA_ACTIVO);
		List<Voluntario> voluntariosActivos = servicioVoluntarioDAO.buscarTodos(DataGenerica.DATA_ACTIVO);
		List<Voluntario> voluntariosInactivos = servicioVoluntarioDAO.buscarTodos(DataGenerica.DATA_INACTIVO);
		for (Reconocimiento reconocimiento : reconocimientos) {
			List<Voluntario> voluntarios;
			if(reconocimiento.getEstadoVoluntario().equals(EstadoVoluntario.ACTIVO))
				voluntarios = voluntariosActivos; 
			else {
				voluntarios = voluntariosActivos;
				voluntarios.addAll(voluntariosInactivos);
			}
			List<PostuladosTemporal> postuladosPreviamente
				= servicioPostuladoTemporalDAO.buscarPorPropiedad("id.reconocimiento", reconocimiento, DataGenerica.DATA_ACTIVO);
			for (PostuladosTemporal postuladoTemporal : postuladosPreviamente)
				voluntarios.remove(postuladoTemporal.getId().getVoluntario());
			List<ReconocimientoVoluntario> reconocimientosVoluntarios
				= servicioReconocimientoVoluntarioDAO.buscarPorPropiedad("reconocimiento", reconocimiento, DataGenerica.DATA_ACTIVO);
			for (ReconocimientoVoluntario reconocimientoVoluntario : reconocimientosVoluntarios)
				voluntarios.remove(reconocimientoVoluntario.getVoluntario());
			postulados.addAll(postular(reconocimiento, voluntarios));
		}
		return postulados;
	}
	
	private List<PostuladosTemporal> postular(Reconocimiento reconocimiento, List<Voluntario> voluntarios) {
		List<PostuladosTemporal> postulados = new ArrayList<PostuladosTemporal>();
		for (Voluntario voluntario : voluntarios) {
			if(verificarCumplimientoHorasRequeridas(reconocimiento, voluntario)
					&& verificarCumplimientoTipoActividadRequerido(reconocimiento, voluntario)
					&& verificarCumplimientoTiempoRequerido(reconocimiento, voluntario)
					&& verificarCumplimientoReconocimientos(reconocimiento, voluntario)
					){
				PostuladosTemporal postuladoTemporal = new PostuladosTemporal();
				PostuladosTemporalId postuladoTemporalId = new PostuladosTemporalId();
				postuladoTemporalId.setReconocimiento(reconocimiento);
				postuladoTemporalId.setVoluntario(voluntario);
				postuladoTemporal.setId(postuladoTemporalId);
				postulados.add(postuladoTemporal);
			}
		}
		return postulados;
	}

	private boolean verificarCumplimientoHorasRequeridas(Reconocimiento reconocimiento, Voluntario voluntario) {
		Date hoy = new Date();
		boolean cumpleHorasRequeridas = false;
		if (reconocimiento.getCantidadMaximaHora() != 0 || reconocimiento.getCantidadMinimaHora() != 0) {
			Date fechaFinConteo = new Date(hoy.getYear(),reconocimiento.getFechaPeriodoOtorgar().getMonth(),reconocimiento.getFechaPeriodoOtorgar().getDate());
			Date fechaInicioConteo = new Date(hoy.getYear()-reconocimiento.getPeriodoContabilizacion(),reconocimiento.getFechaPeriodoOtorgar().getMonth(),reconocimiento.getFechaPeriodoOtorgar().getDate());
			int totalHoras = 0;
			for(AsistenciaVoluntario asistencia : voluntario.getAsistenciaVoluntarios())
				if(reconocimiento.getConteoHoraIngresoVoluntario().equals(RespuestaCerrada.SI)
						|| asistencia.getActividadEjecutada().getFechaFinActividadEjecutada().after(fechaInicioConteo) && asistencia.getActividadEjecutada().getFechaFinActividadEjecutada().before(fechaFinConteo))
					totalHoras += asistencia.getHorasCumplidasVoluntario();
			if(totalHoras >= reconocimiento.getCantidadMinimaHora() && (reconocimiento.getCantidadMaximaHora() == 0 || totalHoras <= reconocimiento.getCantidadMaximaHora()))
				cumpleHorasRequeridas = true;
		} else
			cumpleHorasRequeridas = true;
		return cumpleHorasRequeridas;
	}
	
	private boolean verificarCumplimientoTipoActividadRequerido(Reconocimiento reconocimiento, Voluntario voluntario) {
		for (TipoActividadRequerida tipoActividadRequerida : reconocimiento.getTipoActividadRequeridas()) {
			boolean encontrado = false;
			for(AsistenciaVoluntario asistencia : voluntario.getAsistenciaVoluntarios()) {
				ActividadPlanificada actividadPlanificada = asistencia.getActividadEjecutada().getActividadPlanificadas().iterator().next();
				if(tipoActividadRequerida.getTipoActividad().equals(
						actividadPlanificada.getActividad().getTipoActividad())) {
					encontrado = true;
					break;
				}
			}
			if (!encontrado)
				return false;
		}
		return true;
	}
	
	private boolean verificarCumplimientoTiempoRequerido(Reconocimiento reconocimiento, Voluntario voluntario) {
		Date hoy = new Date();
		boolean cumpleTiempoCrv = false;
		if(reconocimiento.getTiempoMinimoCrv() != 0 || reconocimiento.getTiempoMaximoCrv() != 0) {
			Integer tiempoCrv = new Integer(0);
			Date ingreso = voluntario.getFechaIngresoVoluntario();
			Date auxIngreso = new Date(hoy.getYear(),ingreso.getMonth(),ingreso.getDate());
			if(hoy.before(auxIngreso))
				tiempoCrv = new Integer(hoy.getYear() - ingreso.getYear() - 1);
			else
				tiempoCrv = new Integer(hoy.getYear() - ingreso.getYear());
			if(reconocimiento.getTiempoMinimoCrv() != 0 && reconocimiento.getTiempoMaximoCrv() == 0){
				if(tiempoCrv.intValue()>=reconocimiento.getTiempoMinimoCrv())
					cumpleTiempoCrv = true;
			} else if(tiempoCrv >= reconocimiento.getTiempoMinimoCrv() && tiempoCrv <= reconocimiento.getTiempoMaximoCrv())
				cumpleTiempoCrv = true;
			
		} else
			cumpleTiempoCrv = true;
		return cumpleTiempoCrv;
	}
	
	private boolean verificarCumplimientoReconocimientos(Reconocimiento reconocimiento, Voluntario voluntario) {
		for (ReconocimientoRequerido reconocimientoRequerido :
			reconocimiento.getReconocimientoRequeridosForIdReconocimiento()) {
			boolean encontrado = false;
			for (ReconocimientoVoluntario reconocimientoVoluntario : voluntario.getReconocimientoVoluntarios())
				if (reconocimientoRequerido.getReconocimientoByIdReconocimientoRequisito().equals(reconocimientoVoluntario.getReconocimiento())) {
					encontrado = true;
					break;
				}
			if (!encontrado)
				return false;
		}
		return true;
	}

	public ServicioReconocimientoDAO getServicioReconocimientoDAO() {
		return servicioReconocimientoDAO;
	}

	public void setServicioReconocimientoDAO(
			ServicioReconocimientoDAO servicioReconocimientoDAO) {
		this.servicioReconocimientoDAO = servicioReconocimientoDAO;
	}

	public ServicioVoluntarioDAO getServicioVoluntarioDAO() {
		return servicioVoluntarioDAO;
	}

	public void setServicioVoluntarioDAO(ServicioVoluntarioDAO servicioVoluntarioDAO) {
		this.servicioVoluntarioDAO = servicioVoluntarioDAO;
	}

	public ServicioPostuladoTemporalDAO getServicioPostuladoTemporalDAO() {
		return servicioPostuladoTemporalDAO;
	}

	public void setServicioPostuladoTemporalDAO(
			ServicioPostuladoTemporalDAO servicioPostuladoTemporalDAO) {
		this.servicioPostuladoTemporalDAO = servicioPostuladoTemporalDAO;
	}

	public ServicioReconocimientoVoluntarioDAO getServicioReconocimientoVoluntarioDAO() {
		return servicioReconocimientoVoluntarioDAO;
	}

	public void setServicioReconocimientoVoluntarioDAO(
			ServicioReconocimientoVoluntarioDAO servicioReconocimientoVoluntarioDAO) {
		this.servicioReconocimientoVoluntarioDAO = servicioReconocimientoVoluntarioDAO;
	}

	public void guardarPostulados(List<PostuladosTemporal> listadoPostuladosTemporal) {
		Session session = this.servicioPostuladoTemporalDAO.getSessionFactory().getCurrentSession();
		String hql = "DELETE FROM PostuladosTemporal where id.fechaRegistro >= :ano";
		Date esteAno = new Date();
		esteAno.setDate(1);
		esteAno.setMonth(0);
		Query query = session.createQuery(hql);
		query.setDate("ano",esteAno);
		query.executeUpdate();
		for (PostuladosTemporal postuladosTemporal : listadoPostuladosTemporal)
			this.servicioPostuladoTemporalDAO.guardar(postuladosTemporal);
	}

}
